package cn.lutu.domain.service.impl;


import cn.lutu.cache.ICategoryCacheRepository;
import cn.lutu.domain.repository.CategoryRepository;
import cn.lutu.domain.service.CategoryService;
import cn.lutu.protocol.dto.CategoryAddNewParam;
import cn.lutu.protocol.entity.Category;
import cn.lutu.protocol.vo.CategoryListVO;
import cn.lutu.protocol.vo.CategoryStandardVO;
import cn.lutu.protocol.vo.CategoryTreeVO;
import cn.lutu.util.exception.ServiceException;
import cn.lutu.util.pojo.vo.PageData;
import cn.lutu.util.response.StatusCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;


@Slf4j
@Service
public class CategoryServiceImpl implements CategoryService {
    @Autowired
    CategoryRepository categoryRepository;

    @Autowired
    ICategoryCacheRepository categoryCacheRepository;

    @Value("${lutu.dao.default-query-page-size}")
    private Integer defaultQueryPageSize;

    @Override
    public void addNew(CategoryAddNewParam categoryAddNewParam) {
        log.info("开始执行新增类别的业务");
        if(categoryAddNewParam.getParentId() == null){
            categoryAddNewParam.setParentId(0L);
        }
        int count = categoryRepository.selectByName(categoryAddNewParam.getName());
        if(count > 0){
            String message = "该类别已存在，请重新提交！";
            log.info(message);
            throw new ServiceException(StatusCode.ERROR_CONFLICT,message);
        }
         Category categoryVO = categoryRepository.selectById(categoryAddNewParam.getParentId());
        if(categoryAddNewParam.getParentId() != 0 && categoryVO == null){
            String message = "该类别的父级类别不存在，请重新提交！";
            log.info(message);
            throw new ServiceException(StatusCode.ERROR_CONFLICT,message);
        }
        Category category = new Category();
        Integer categoryLevel = 1;
        if(categoryAddNewParam.getParentId() != 0){
            categoryLevel = categoryVO.getCategoryLevel()+1;
        }
        BeanUtils.copyProperties(categoryAddNewParam,category);
        category.setCategoryLevel(categoryLevel);
        category.setSort(99);
        category.setEnable(1);
        category.setIsParent(0);
        int rows = categoryRepository.insert(category);
        log.debug("新增结束,受影响的行数为{}",rows);
        if(rows != 1){
            String message = "服务器忙，请稍后再试！";
            log.info(message);
            throw new ServiceException(StatusCode.ERROR_UNKNOWN,message);
        }

        if( categoryVO != null && categoryVO.getIsParent() == 0){
            Category categoryParent = new Category();
            categoryParent.setIsParent(1);
            categoryParent.setId(categoryVO.getId());
            rows = categoryRepository.updateById(categoryParent);
            log.debug("修改父类的ISPARENT结束,受影响的行数为{}",rows);
            if(rows != 1){
                String message = "服务器忙，请稍后再试！";
                log.info(message);
                throw new ServiceException(StatusCode.ERROR_UNKNOWN,message);
            }

        }
    }

    @Override
    public void deleteById(Long id) {
        log.info("开始执行根据ID删除类别的业务");
        Category category = categoryRepository.selectById(id);
        if (category == null || category.getIsParent() == 1) {
            String message = "删除类别失败，尝试删除的数据不存在！";
            log.warn(message);
            throw new ServiceException(StatusCode.ERROR_NOT_FOUND, message);
        }

        int rows = categoryRepository.deleteById(id);
        if (rows != 1) {
            String message = "删除类别失败，服务器忙，请稍后再试！";
            log.warn(message);
            throw new ServiceException(StatusCode.ERROR_UNKNOWN, message);
        }
    }

    @Override
    public void updateById(CategoryAddNewParam categoryAddNewParam) {
        log.debug("开始执行更新类别的业务");
        /*判断请求的类别是否存在*/
        CategoryStandardVO categoryStandardVO = categoryRepository.selectStandardById(categoryAddNewParam.getId());
        if(categoryStandardVO == null){
            String message = "修改类别失败，尝试修改的数据不存在！";
            log.warn(message);
            throw new ServiceException(StatusCode.ERROR_NOT_FOUND, message);
        }
        /*判断修改后的父类类别是否为父类,若不是,则修改为父类*/
        CategoryStandardVO categoryParent = categoryRepository.selectStandardById(categoryAddNewParam.getParentId());
        if(categoryParent.getIsParent() == 0){
            log.debug("判断修改后的父类是否是父类");
            Category parentCategory = new Category();
            parentCategory.setIsParent(1);
            parentCategory.setId(categoryParent.getId());
            int rows = categoryRepository.updateById(parentCategory);
            if(rows != 1){
                String message = "服务器忙,请稍后再试";
                log.warn(message);
                throw new ServiceException(StatusCode.ERROR_UNKNOWN, message);
            }
        }
        /*判断修改之前的类别是否还存在子类,不存在则修改IsParent为0,先查出对应的原来的父类对象备用*/
        CategoryStandardVO oldParent = categoryRepository.selectStandardById(categoryStandardVO.getParentId());
        if(oldParent == null){
            String message = "请提交合法的值";
            log.warn(message);
            throw new ServiceException(StatusCode.ERROR_NOT_FOUND, message);
        }
        /*修改请求的类型*/
        Category category = new Category();
        BeanUtils.copyProperties(categoryAddNewParam,category);
        category.setCategoryLevel(categoryParent.getCategoryLevel()+1);
        int rows = categoryRepository.updateById(category);
        if(rows != 1){
            String message = "服务器忙,请稍后再试";
            log.warn(message);
            throw new ServiceException(StatusCode.ERROR_UNKNOWN, message);
        }
        /*判断原来的父类是否还有子类，没有则修改IsParent*/
        int count = categoryRepository.selectCount(oldParent.getId());
        if(count == 0){
            Category oldParentUpdate = new Category();
            oldParentUpdate.setId(oldParent.getId());
            oldParentUpdate.setIsParent(0);
            rows = categoryRepository.updateById(oldParentUpdate);
            if(rows != 1){
                String message = "服务器忙,请稍后再试";
                log.warn(message);
                throw new ServiceException(StatusCode.ERROR_UNKNOWN, message);
            }
        }
    }

    @Override
    public PageData<CategoryListVO> getCategories(Integer pageNum, Integer pageSize) {
        log.info("开始执行查询类别列表的业务");
        PageData<CategoryListVO> pageData = categoryRepository.selectCategories(pageNum, pageSize);
        return pageData;
    }

    @Override
    public PageData<CategoryListVO> getCategories(Integer pageNum) {
        log.debug("开始处理【查询标签列表】的业务，页码：{}", pageNum);
        PageData<CategoryListVO> pageData = categoryRepository.selectCategories(pageNum, defaultQueryPageSize);
        return pageData;
    }

    @Override
    public CategoryStandardVO selectStandardVOById(Long id) {
        log.debug("开始根据ID查询标准类别,id为{}",id);
        CategoryStandardVO categoryStandardVO = categoryRepository.selectStandardById(id);
        if(categoryStandardVO == null){
            String message = "该类别不存在,请重新提交";
            log.info(message);
            throw new ServiceException(StatusCode.ERROR_UNKNOWN,message);
        }
        return categoryStandardVO;
    }

    @Override
    public Category selectById(Long id) {
        log.info("开始处理根据ID{}【查询标签列表】的业务", id);
        Category category = categoryRepository.selectById(id);
        if(category == null){
            String message = "该类别不存在,请重新提交";
            log.info(message);
            throw new ServiceException(StatusCode.ERROR_UNKNOWN,message);
        }
        return category;
    }

    @Override
    public List<CategoryTreeVO> getCategoryTree(Long id) {
        log.info("开始执行获取类型树的业务");
        List<CategoryTreeVO> categoryTree = new ArrayList<>();
        List<CategoryListVO> categoryList = categoryRepository.getCategoryList();
        Map<Long,CategoryListVO> categoryMap = transformListToMap(categoryList);
        for(Long key :categoryMap.keySet()){
            CategoryListVO item = categoryMap.get(key);
            if(item.getParentId()==id){
                CategoryTreeVO categoryTreeVO = convertListVOToTreeVO(item);
                categoryTree.add(categoryTreeVO);
                fillChildren(item,categoryTreeVO,categoryMap);
            }
        }
        return categoryTree;
    }

    @Override
    public List<CategoryListVO> getCategoryListByParentId(Long parentId) {
        log.info("开始执行根据parentId获取类型的业务");
        Category category = categoryRepository.selectById(parentId);
        if(parentId != 0) {
            if (category == null) {
                String message = "该类别不存在,请重新提交查询！";
                log.info(message);
                throw new ServiceException(StatusCode.ERROR_NOT_FOUND, message);
            }
            if (category.getIsParent() == 0) {
                String message = "该类别没有子级,请重新提交查询！";
                log.info(message);
                throw new ServiceException(StatusCode.ERROR_NOT_FOUND, message);
            }
        }
        List<CategoryListVO> categoryByParentId = categoryRepository.getCategoryByParentId(parentId);
        log.info("service查询到的数据为{}",categoryByParentId);

        return categoryByParentId;
    }

    private void fillChildren(CategoryListVO item,CategoryTreeVO categoryTreeVO,Map<Long,CategoryListVO> categoryMap){
        System.out.println("item = " + item + ", categoryTreeVO = " + categoryTreeVO + ", categoryMap = " + categoryMap);
        if(item.getIsParent() == 1){
            categoryTreeVO.setChildren(new ArrayList<>());
            Set<Long> keySet = categoryMap.keySet();
            for(Long key:keySet){
                CategoryListVO childrenItem = categoryMap.get(key);
                if(childrenItem.getParentId() == item.getId()){
                    CategoryTreeVO categoryTreeVOChildren =convertListVOToTreeVO(childrenItem);
                    categoryTreeVO.getChildren().add(categoryTreeVOChildren);
                    if(childrenItem.getIsParent() == 1){
                        fillChildren(childrenItem,categoryTreeVOChildren,categoryMap);
                    }
                }
            }
        }
    }

    private Map<Long,CategoryListVO> transformListToMap(List<CategoryListVO> list){
       Map<Long,CategoryListVO> map = new HashMap<>();
        for(CategoryListVO categoryListVO: list){
            map.put(categoryListVO.getId(),categoryListVO);
        }
        return map;
    }

    private CategoryTreeVO convertListVOToTreeVO(CategoryListVO categoryListVO){
        return new CategoryTreeVO()
                .setValue(categoryListVO.getId())
                .setLabel(categoryListVO.getName());
    }
}
